package com.me.libgdx_test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent;

//Works like the director in the selection screen
//Arranges all the sprites and adds click actions to them
//This director also add buttons and descriptions...
public class ClassMarketDirector {
	
	//These need to be widgets so we can add them to the scene later
	private ArrayList<ClassMarketItem> tavern_options,market_options,inn_options, bank_options;
	//This holds all of the individual items defined by the ClassMarketItem class
	private Group switch_group;
	private ClassSkinReference skin;
	private ClassLogDisplay logger;
	private Point location, dimensions;
	private ClassUnlockables unlockables;
	private Class[] parameterTypes;
	private Class<?> factory_root;
	private Method last_invoked;
	private Object market_activity;
	private ActivityMain game;
	private Stage stage;
	ClassMarketDirector(Stage stage, Group switch_group, Point dimensions, Point location, 
			ClassUnlockables unlockables, Object market_activity, ActivityMain game){
		tavern_options = new ArrayList<ClassMarketItem>();
		market_options = new ArrayList<ClassMarketItem>();
		inn_options = new ArrayList<ClassMarketItem>();
		bank_options = new ArrayList<ClassMarketItem>();
		//The switch table is a pointer to the layout on the market_list page
		this.stage = stage;
		this.switch_group = switch_group;
		this.location = location;
		this.dimensions = dimensions;
		logger = new ClassLogDisplay("ClassMarketDirector");
		this.unlockables = unlockables;
		this.skin = game.skin;
		parameterTypes = new Class[1];
        parameterTypes[0] = int.class;
        factory_root = unlockables.get_unlockable_prototypes().get_factory().getClass();
        this.market_activity = market_activity;
        this.game = game;
	}
	public void add_tavern_option(Sprite picture, String title, String description, String button_text, final int reference_index, ClassUnlockCost cost) throws NoSuchMethodException, SecurityException{
		//logger.print("Class: " + reference_index);
		//Im passing the skins in here because I am assuming that this is an expensive object to keep creating...
		tavern_options.add(new ClassMarketItem(stage, picture, title, description, dimensions, location, skin, button_text, 
				unlockables.get_unlockable_prototypes().get_factory(),
				factory_root.getDeclaredMethod("unlock_class", parameterTypes),
				reference_index,game,market_activity,this,cost));
	}
	public void add_market_option(Sprite picture, String title, String description, String button_text, int reference_index, ClassUnlockCost cost) throws NoSuchMethodException, SecurityException{
		//logger.print("Upgrade: " + reference_index);
		//Im passing the skins in here because I am assuming that this is an expensive object to keep creating...
		market_options.add(new ClassMarketItem(stage, picture, title, description, dimensions, location, skin, button_text,
				unlockables.get_unlockable_prototypes().get_factory(),
				factory_root.getMethod("unlock_upgrade", parameterTypes),
				reference_index,game,market_activity,this,cost));
	}
	public void add_inn_option(Sprite picture, String title, String description, String button_text, int reference_index, ClassUnlockCost cost) throws NoSuchMethodException, SecurityException{
		//logger.print("Spell: " + reference_index);
		//Im passing the skins in here because I am assuming that this is an expensive object to keep creating...
		inn_options.add(new ClassMarketItem(stage, picture, title, description, dimensions, location, skin, button_text,
				unlockables.get_unlockable_prototypes().get_factory(),
				factory_root.getMethod("unlock_spell", parameterTypes),
				reference_index,game,market_activity,this,cost));
	}
	public void add_bank_option(Sprite picture, String title, String description, String button_text, int reference_index, ClassUnlockCost cost) throws NoSuchMethodException, SecurityException{
		/*bank_options.add(new ClassMarketItem(picture, description, dimensions, location, skin, button_text,
				unlockables.get_unlockable_prototypes().get_factory(),
				factory_root.getMethod("bank_loan", parameterTypes),
				reference_index,game,market_activity,this,cost));*/
		
		logger.print("Add Bank Options");
		
		Class[] alt_parameterTypes = new Class[4];
		alt_parameterTypes[0] = String.class;
		alt_parameterTypes[1] = int.class;
		alt_parameterTypes[2] = Object.class;
		alt_parameterTypes[3] = Method.class;
		
		for(Method method_name: game.billing.getClass().getMethods()){
			logger.print("Method: " + method_name.getName());
			for(Class<?> type:method_name.getParameterTypes()){
				logger.print("Type: " + type.getName());
			}
		}
		
		bank_options.add(new ClassMarketItem(stage, picture, title, description, dimensions, location, skin, button_text,
			game.billing,
			game.billing.getClass().getMethod("submitPurchase", alt_parameterTypes),
			reference_index,game,market_activity,this,cost));
	}
	public int get_tavern_size(){
		//logger.print("Tavern size: " + tavern_options.size());
		return tavern_options.size();
	}
	public int get_market_size(){
		//logger.print("Market size: " + market_options.size());
		return market_options.size();
	}
	public int get_inn_size(){
		//logger.print("Inn size: " + inn_options.size());
		return inn_options.size();
	}
	public ArrayList<ClassMarketItem> get_market_list(){
		return market_options;
	}
	public void update_market_description(String description, int index){
		market_options.get(index).update_description(description);
	}
	public void update_market_cost(ClassUnlockCost cost, int index){
		market_options.get(index).update_cost(cost);
	}
	public boolean value_in_tavern(int index){
		for(ClassMarketItem tavern:tavern_options){
			if(tavern.get_click_index() == index){
				return true;
			}
		}
		return false;
	}
	public boolean value_in_market(int index){
		for(ClassMarketItem market:market_options){
			if(market.get_click_index() == index){
				return true;
			}
		}
		return false;
	}
	public boolean value_in_inn(int index){
		for(ClassMarketItem inn:inn_options){
			if(inn.get_click_index() == index){
				return true;
			}
		}
		return false;
	}
	public void reset_options(){
		ArrayList<ClassMarketItem> new_tavern = new ArrayList<ClassMarketItem>();
		for(ClassMarketItem tavern:tavern_options){
			if(!unlockables.get_unlockable_prototypes().get_factory().get_class_unlocked(tavern.get_click_index())){
				new_tavern.add(tavern);
			}
		}
		tavern_options = new_tavern;
		
		ArrayList<ClassMarketItem> new_market = new ArrayList<ClassMarketItem>();
		for(ClassMarketItem market:market_options){
			if(unlockables.get_unlockable_prototypes().get_factory().get_upgrade_at_id(market.get_click_revised_click_index())<10){
				new_market.add(market);
			}
		}
		market_options = new_market;
		
		ArrayList<ClassMarketItem> new_inn = new ArrayList<ClassMarketItem>();
		for(ClassMarketItem inn:inn_options){
			if(!unlockables.get_unlockable_prototypes().get_factory().get_spell_unlocked(inn.get_click_index())){
				new_inn.add(inn);
			}
		}
		inn_options = new_inn;
		
		bank_options = new ArrayList<ClassMarketItem>();
	}
	public void set_last_options(){
		try {
			this.last_invoked.invoke(this, new Object[0]);
			logger.print("Last invoked reflect: " + this.last_invoked.getName());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	public void set_tavern_options() throws NoSuchMethodException, SecurityException{
		float y_offset = (dimensions.y/2)/5;
		float current_y = 0;
		switch_group.clear();
		for(ClassMarketItem item: tavern_options){
			item.construct_market_item(switch_group,current_y,1);
			current_y += y_offset;
		}
		last_invoked = ClassMarketDirector.class.getMethod("set_tavern_options", new Class[0]);
		logger.print("Last invoked: " + last_invoked.getName());
	}
	public void set_market_options() throws NoSuchMethodException, SecurityException{
		float y_offset = (dimensions.y/2)/5;
		float current_y = 0;
		switch_group.clear();
		for(ClassMarketItem item: market_options){
			item.construct_market_item(switch_group,current_y,1.1f);
			current_y += y_offset;
		}
		last_invoked = ClassMarketDirector.class.getMethod("set_market_options", new Class[0]);
		logger.print("Last invoked: " + last_invoked.getName());
	}
	public void set_inn_options() throws NoSuchMethodException, SecurityException{
		float y_offset = (dimensions.y/2)/5;
		float current_y = 0;
		switch_group.clear();
		for(ClassMarketItem item: inn_options){
			item.construct_market_item(switch_group,current_y,1.3f);
			current_y += y_offset;
		}
		last_invoked = ClassMarketDirector.class.getMethod("set_inn_options", new Class[0]);
		logger.print("Last invoked: " + last_invoked.getName());
	}
	public void set_bank_options() throws NoSuchMethodException, SecurityException{
		float y_offset = (dimensions.y/2)/5;
		float current_y = 0;
		switch_group.clear();
		for(ClassMarketItem item: bank_options){
			item.construct_market_item(switch_group,current_y,1.3f);
			current_y += y_offset;
		}
		last_invoked = ClassMarketDirector.class.getMethod("set_bank_options", new Class[0]);
		logger.print("Last invoked: " + last_invoked.getName());
	}
}
